home *** CD-ROM | disk | FTP | other *** search
- /* alarm.c
- *****************************************************************************
- expecTerm version 1.0 beta
- Mark Weissman
- Christopher Matheus
- Copyright 1992 by GTE Laboratories Incorporated.
-
- Portions of this work are in the public domain. Permission to use,
- copy, modify, and distribute this software and its documentation for
- any purpose and without fee is hereby granted, provided that the above
- copyright notice appear in all copies and that both the copyright
- notice and warranty disclaimer appear in supporting documentation, and
- that the names of GTE Laboratories or any of their entities not be
- used in advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- GTE disclaims all warranties with regard to this software, including
- all implied warranties of merchantability and fitness for a particular
- purpose, even if GTE Laboratories Incorporated knows about the
- purpose. In no event shall GTE be liable for any special, indirect or
- consequential damages or any damages whatsoever resulting from loss of
- use, data or profits, whether in an action of contract, negligence or
- other tortuous action, arising out of or in connection with the use or
- performance of this software.
-
- This code is based on and may include parts of Don Libes' expect code:
- expect written by: Don Libes, NIST, 2/6/90
- Design and implementation of expect was paid for by U.S. tax
- dollars. Therefore it is public domain. However, the author and NIST
- would appreciate credit if this program or parts of it are used.
- ******************************************************************************/
-
- #include <stdio.h>
- #include <setjmp.h>
- #include <signal.h>
- #include <sys/time.h> /* for time(3) */
- #include <tcl.h>
- #include "compat.h"
- #include "translate.h"
- #include "global.h"
- static jmp_buf env; /* for interruptable read() */
- static int env_valid = FALSE; /* whether we can longjmp or not */
- typedef void (*VFPTR)();
- VFPTR Signal();
-
- struct timeval *AddTimeval(t1,t2)
- struct timeval *t1, *t2;
- {
- t1->tv_sec += t2->tv_sec;
- t1->tv_usec += t2->tv_usec;
- if (t1->tv_usec >= uS_PER_SEC) {
- t1->tv_usec -= uS_PER_SEC;
- t1->tv_sec += 1;
- }
- return(t1);
- }
-
- struct timeval *SubtractTimeval(t1,t2)
- struct timeval *t1, *t2;
- {
- if (t1->tv_usec < t2->tv_usec) {
- if (t1->tv_sec < 1) t2 = t1;
- else {
- t1->tv_usec += uS_PER_SEC;
- t1->tv_sec -= 1;
- }
- }
- if (t1->tv_sec < t2->tv_sec) t2 = t1;
- t1->tv_sec -= t2->tv_sec;
- t1->tv_usec -= t2->tv_usec;
- return(t1);
- }
-
- struct timeval *DoubleToTimeval(t, tv)
- double t;
- struct timeval *tv;
- {
- static struct timeval tv_struct;
- if (!tv) tv = &tv_struct;
-
- tv->tv_sec = (unsigned) t;
- tv->tv_usec = (unsigned) ((double)uS_PER_SEC * (t - tv->tv_sec));
- return(tv);
- }
-
- double TimevalToDouble(tv)
- struct timeval *tv;
- {
- if (!tv) return(100000.0);
- else return((double)tv->tv_sec + ((double)tv->tv_usec)/(double)uS_PER_SEC);
- }
-
- double TimeOfDay() {
- struct timeval tv;
- gettimeofday(&tv,NULL);
- return((double)tv.tv_sec + ((double)tv.tv_usec)/(double)uS_PER_SEC);
- }
-
- /*ARGSUSED*/
- void
- sigalarm_handler(n)
- int n; /* unused, for compatibility with STDC */
- {
- #ifdef REARM_SIG
- Signal(SIGALRM,sigalarm_handler);
- #endif
-
- /* check env_valid first to protect us from the alarm occurring */
- /* in the window between i_read and alarm(0) */
- if (env_valid) longjmp(env,1);
- }
-
- /* upon interrupt, act like timeout */
- /*ARGSUSED*/
- void
- sigint_handler(n)
- int n; /* unused, for compatibility with STDC */
- {
- #ifdef REARM_SIG
- Signal(SIGINT,sigint_handler);/* not nec. for BSD, but doesn't hurt */
- #endif
-
- /* longjmp if we are executing a read inside of expect command */
- if (env_valid) longjmp(env,1);
-
- /* if anywhere else in code, prepare to exit */
- bye(0);
- }
-
- VoidFuncArray init_expect_alarms(sigfuncs, flags)
- unsigned flags;
- void (*sigfuncs[])();
- {
- static void (*isigfuncs[32])();
- extern char *signal_to_string();
- int n;
- if (!sigfuncs) sigfuncs = isigfuncs;
- for (n=0; n<32; ++n) {
- if (flags & (1<<n)) {
- debuglog("signal(%s:%d, %s)\n", signal_to_string(n), n, (n==SIGINT)?"sigint_handler":"sigalarm_handler");
- if (n==SIGINT)
- sigfuncs[n]=Signal(n,sigint_handler);
- else
- sigfuncs[n]=Signal(n,sigalarm_handler);
- }
- else sigfuncs[n]=NULL;
- }
- return(sigfuncs);
- }
-
-
-
- Ualarm(value, interval)
- unsigned value, interval;
- {
- struct itimerval it;
- it.it_value.tv_sec = value / uS_PER_SEC;
- it.it_value.tv_usec = value % uS_PER_SEC;
- it.it_interval.tv_sec = interval / uS_PER_SEC;
- it.it_interval.tv_usec = interval % uS_PER_SEC;
- setitimer(ITIMER_REAL, &it, NULL);
- }
-
- SetAlarm(wakeup)
- double wakeup;
- {
- if (setjmp(env) != 1) {
- env_valid = TRUE;
- if (wakeup != -1.0) {
- unsigned t = (unsigned)(wakeup*(double)uS_PER_SEC);
- ualarm(t,0);
- }
- return(1);
- }
- else return(0);
- }
-
- ClearAlarm()
- {
- alarm(0);
- env_valid = FALSE;
- }
-
- AlarmReturn(val)
- int val;
- {
- if (env_valid) longjmp(env,val);
- else return(0);
- }
-
- VFPTR Signal(sig, func)
- int sig;
- void (*func)();
- {
- #ifdef _AIX
- struct sigaction action, oaction;
- action.sa_flags = SA_RESTART & ~SA_ONSTACK & ~SA_OLDSTYLE & ~SA_NOCLDSTOP;
- action.sa_mask.losigs = 0;
- action.sa_mask.hisigs = 0;
- action.sa_handler = func;
- if (sigaction(sig, &action, &oaction) == 0) /* success */
- return(oaction.sa_handler);
- else return((VFPTR)-1);
- #else
- #ifdef _HP
- return(signal(sig, func));
- #else
- struct sigvec vec, ovec;
- vec.sv_flags = ~SV_ONSTACK & ~SV_INTERRUPT & ~SV_RESETHAND;
- vec.sv_mask = 1<<sig;
- vec.sv_handler = func;
- if (sigvec(sig, &vec, &ovec) == 0) /* success */
- return(ovec.sv_handler);
- else return((VFPTR)-1);
- #endif
- #endif
- }
-
-